package com.gzxx.security;

import com.gzxx.constant.RedisCacheConstant;
import com.gzxx.util.GsonUtil;
import com.gzxx.util.Identities;
import com.gzxx.util.JwtOperator;
import com.redisdatastorage.cache.RedisCache;
import io.jsonwebtoken.Claims;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;

/**
 * @author MAX
 * @date 2020/7/24 1:33 下午
 */
@Component
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class TokenService {

    private final JwtOperator jwtOperator;
    private final RedisCache redisCache;

    private static final long REFRESH_TOKEN_TIME_MAX = 5 * 60;
    private static final long REFRESH_TOKEN_TIME_MIN = 10;


    /**
     * 创建token，并将认证用户信息存储到redis
     *
     * @param currentUser 认证用户
     * @return token
     */
    public String createToken(CurrentUser currentUser) {
        //生成唯一性标识
        String uuid = Identities.uuid(false);
        redisCache.set(RedisCacheConstant.CURRENT_LOGIN_USER_KEY + uuid, GsonUtil.toJson(currentUser), RedisCacheConstant.BACKEND_USER_TOKEN_VALIDITY);
        Map<String, Object> claims = new HashMap<>(2);
        claims.put("identifier", uuid);
        return jwtOperator.generateToken(claims);
    }

    /**
     * 获取认证用户信息
     *
     * @param request HttpServletRequest
     * @return 用户认证信息
     */
    public CurrentUser getLoginUser(HttpServletRequest request) {
        String token = getToken(request);
        if (StringUtils.hasLength(token)) {
            Claims claims = jwtOperator.parseToken(token);
            // 解析对应的权限以及用户信息
            String uuid = (String) claims.get("identifier");
            String json = redisCache.get(RedisCacheConstant.CURRENT_LOGIN_USER_KEY + uuid);
            return GsonUtil.fromJson(json, CurrentUser.class);
        }
        return null;
    }

    /**
     * 刷新token
     *
     * @param request request
     */
    public void refreshToken(HttpServletRequest request) {
        String token = getToken(request);
        Claims claims = jwtOperator.parseToken(token);
        String uuid = (String) claims.get("identifier");
        //获取key的剩余存活时间，大于10s小于5分钟则重置为1天
        long second = redisCache.getValidity(uuid);
        if (second > REFRESH_TOKEN_TIME_MIN && second < REFRESH_TOKEN_TIME_MAX) {
            redisCache.expire(RedisCacheConstant.CURRENT_LOGIN_USER_KEY + uuid, RedisCacheConstant.BACKEND_USER_TOKEN_VALIDITY);
        }
    }

    /**
     * 获取请求token
     *
     * @param request HttpServletRequest
     * @return token
     */
    private String getToken(HttpServletRequest request) {
        String authorization = request.getHeader("Authorization");
        if (StringUtils.hasLength(authorization) && authorization.startsWith("Bearer")) {
            return authorization.substring(7);
        }
        return null;
    }

    /**
     * 删除token，并将认证用户信息从redis移除
     *
     * @param request HttpServletRequest
     * @return token
     */
    public boolean removeToken(HttpServletRequest request) {
        String token = getToken(request);
        if (StringUtils.hasLength(token)) {
            Claims claims = jwtOperator.parseToken(token);
            //获取uuid
            String uuid = (String) claims.get("identifier");
            String currentUserKey = RedisCacheConstant.CURRENT_LOGIN_USER_KEY + uuid;
            //remove to redis if key exists
            if (redisCache.hasKey(currentUserKey)) {
                return redisCache.delete(currentUserKey);
            }
        }
        return false;
    }
}
